package com.mew.common.dc.db;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mew.common.config.RedisConstantValue;
import com.mew.common.dc.mapper.GoldRecordMapper;
import com.mew.common.dc.mapper.ProfileMapper;
import com.mew.common.enm.GoldProcessType;
import com.mew.common.entity.record.GoldRecord;
import com.mew.common.entity.user.Profile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;


/**
 * @Author K.Song
 * @Date 2020/11/6 0006
 **/
@Service
@Slf4j
public class ProfileService {

    @Autowired
    private ProfileMapper profileMapper;
    @Autowired
    private GoldRecordMapper goldRecordMapper;
    @Autowired
    private DefaultRedisScript<Long> profileScript;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public Profile createProfile(long userId, long registerNumber){
        Profile profile = new Profile();
        profile.setUserId(userId);
        profile.setGoldNumber(registerNumber);
        profileMapper.insert(profile);
        //-------------
        profile.initData();
        putRedis(profile);
        return profile;
    }

    public Profile getRedisProfileById(long userId){
        Profile profile = (Profile) redisTemplate.opsForHash().get(RedisConstantValue.USER_PROFILE, userId);
        if (profile == null){
            profile = profileMapper.selectById(userId);
             if (null != profile){
                 redisTemplate.opsForHash().put(RedisConstantValue.USER_PROFILE, userId, profile);
             }
        }
        return profile;
    }

    public Profile getProfileById(long userId){
        Profile profile = profileMapper.selectById(userId);
        if (null != profile){
            redisTemplate.opsForHash().put(RedisConstantValue.USER_PROFILE, userId, profile);
        }else {
            redisTemplate.opsForHash().delete(RedisConstantValue.USER_PROFILE, userId);
        }
        return profile;
    }

    private void putRedis(Profile profile){
        redisTemplate.opsForHash().put(RedisConstantValue.USER_PROFILE, profile.getUserId(), profile);
    }

    public List<Profile> findAll(int pid, int size){
        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<Profile>()
                .eq(Profile::getUserLevel, 1)
                .last(StrUtil.format("ORDER BY user_id DESC LIMIT {}, {}", pid, size));
        List<Profile> list = profileMapper.selectList(queryWrapper);
        for (Profile profile : list){
            putRedis(profile);
        }
        return list;
    }
    //------操作金币---------
    public Profile doGold(Profile profile, long goldNumber, GoldProcessType type){
        if (goldNumber==0){
            return profile;
        }

        long oldGold = profile.getGoldNumber();

        if(oldGold+goldNumber<0){
            return profile;
        }
        profile.setGoldNumber(profile.getGoldNumber() + goldNumber);

        Profile db = new Profile();
        db.setUserId(profile.getUserId());
        db.setGoldNumber(goldNumber);
        updateProfile(profile, db);

        GoldRecord goldRecord = GoldRecord.builder()
                .userId(profile.getUserId())
                .processNumber(goldNumber)
                .processType(type.code())
                .goldNumber(oldGold)
                .build();
        goldRecordMapper.insert(goldRecord);
        return profile;
    }

    //------操作金币---------
    public void doGold(Profile profile, long goldNumber,long jewelNumber,double jewelMoney, int type){
        if (goldNumber==0&&jewelNumber==0&&jewelMoney==0){
            return;
        }

        long oldGold = profile.getGoldNumber();
        long oldJewel = profile.getJewelNumber();
        profile.setGoldNumber(profile.getGoldNumber() + goldNumber);
        profile.setJewelNumber(profile.getJewelNumber() + jewelNumber);
        oldGold = profile.getGoldNumber();

        Profile db = new Profile();
        db.setUserId(profile.getUserId());
        db.setGoldNumber(goldNumber);
        db.setJewelNumber(jewelNumber);
        updateProfile(profile, db);

        if (goldNumber>0){
            GoldRecord goldRecord = GoldRecord.builder()
                    .userId(profile.getUserId())
                    .processNumber(goldNumber)
                    .processType(type)
                    .goldNumber(oldGold)
                    .build();
            goldRecordMapper.insert(goldRecord);
        }
        if (jewelNumber>0){
            //记录
//            jewelRecordMapper.insert(JewelRecord
//                    .builder()
//                    .userId(profile.getUserId())
//                    .buyType(type)
//                    .buyMoney(jewelMoney)
//                    .buyNumber(jewelNumber)
//                    .beforeNumber(oldJewel)
//                    .build());
        }

    }

    public Profile doGold(long userId, long goldNumber){
        Profile profile = getRedisProfileById(userId);
        profile.setGoldNumber(profile.getGoldNumber() + goldNumber);

        Profile db = new Profile();
        db.setUserId(userId);
        db.setGoldNumber(goldNumber);
        updateProfile(profile, db);

        return profile;
    }

    public Profile doGold(long userId, long goldNumber, GoldProcessType type){
        Profile profile = getRedisProfileById(userId);
        return doGold(profile, goldNumber, type);
    }

    public Profile doGold(long userId, long goldNumber,long jewelNumber,double jewelMoney, int type){
        Profile profile = getRedisProfileById(userId);
        doGold(profile, goldNumber, jewelNumber,jewelMoney,type);
        return profile;
    }

    public void updateProfile(Profile profile, Profile dbProfile, GoldProcessType type){
        updateProfile(profile, dbProfile);

        GoldRecord goldRecord = GoldRecord.builder()
                .userId(profile.getUserId())
                .processNumber(dbProfile.getGoldNumber())
                .processType(type.code())
                .goldNumber(profile.getGoldNumber() - dbProfile.getGoldNumber())
                .build();
        goldRecordMapper.insert(goldRecord);
    }


    public void updateProfile(Profile profile, Profile dbProfile){
        profileMapper.updateByAuto(dbProfile);
//        putRedis(profile);
        updateRedisByAuto(dbProfile);
    }

    public void updateProfile(Profile dbProfile){
        profileMapper.updateByAuto(dbProfile);
        getProfileById(dbProfile.getUserId());
    }

    public void deleteByUserId(long userId){
        redisTemplate.opsForHash().delete(RedisConstantValue.USER_PROFILE, userId);
    }

    private long updateRedisByAuto(Profile profile){
        long res =  redisTemplate.execute(profileScript, Arrays.asList(String.valueOf(profile.getUserId())),
                profile.getGoldNumber(), profile.getJewelNumber(), profile.getVipLevel(), profile.getUserLevel(),
                profile.getPlayTotal(), profile.getBetTotal(), profile.getPaymentTotal()
        );
        return res;
    }

}
